/*     */ package com.hp.bon.sgw.wkflow;
/*     */ 
/*     */ /*     */ import java.text.SimpleDateFormat;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Properties;

/*     */ import org.dom4j.Document;
/*     */ import org.dom4j.Element;
/*     */ import org.slf4j.Logger;
/*     */ import org.slf4j.LoggerFactory;

import bsh.EvalError;
/*     */ import bsh.Interpreter;

/*     */ import com.gadberry.utility.expression.InvalidExpressionException;
import com.hp.bon.sgw.Constants;
/*     */ import com.hp.bon.sgw.bean.XmlMessage;
/*     */ import com.hp.bon.sgw.convert.Xml2AVPConvetor;
/*     */ import com.hp.bon.sgw.core.CallParam;
/*     */ import com.hp.bon.sgw.core.ChannelServer;
/*     */ import com.hp.bon.sgw.core.InprogressMessageQueue;
/*     */ import com.hp.bon.sgw.core.processor.Processor;
/*     */ import com.hp.bon.sgw.core.route.RouteInfo;
import com.hp.bon.sgw.domain.ConvMapInfo;
/*     */ import com.hp.bon.sgw.util.Comutils;
/*     */ import com.hp.bon.sgw.util.dcc.DccAvpHelper;
/*     */ import com.hp.bon.sgw.util.dcc.DccMessageBuilder;
/*     */ import com.hp.bon.sgw.util.dcc.MessageDef;
/*     */ import com.hp.bon.sgw.wkflow.impl.DCCMsgVarObj;
/*     */ import com.hp.bon.sgw.wkflow.impl.FlowInputDataVarObj;
/*     */ import com.hp.bon.sgw.wkflow.impl.FlowInputVarObj;
/*     */ import com.hp.ocs.diameter.DiameterUtils;
import com.hp.ocs.diameter.ProtocolConstants;
/*     */ import com.hp.ocs.diameter.message.AVP;
/*     */ import com.hp.ocs.diameter.message.AVP_Grouped;
/*     */ import com.hp.ocs.diameter.message.AVP_OctetString;
/*     */ import com.hp.ocs.diameter.message.AVP_UTF8String;
/*     */ import com.hp.ocs.diameter.message.AVP_Unsigned32;
/*     */ import com.hp.ocs.diameter.message.Message;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class SGWFlowInstance extends Processor{

	private static final Logger logger = LoggerFactory.getLogger(SGWFlowInstance.class);

	private String flowID;
	/**
	 * 对应的流程定义
	 */
	private final FlowDef flowDef;

	/**
	 * 当前执行的STEP
	 */
	private volatile FlowStepStatus curStepStaus;

	private FlowExpressionParser flowExprParser;
	/**
	 * 是否执行完成
	 */
	private volatile boolean finished;

	private CallParam originCallParam;
	private Interpreter bsh;

	/**
	 * 启动执行Flow
	 * 
	 * @throws Exception
	 */

	public SGWFlowInstance(FlowDef flowDef) {
		this.flowDef = flowDef;
	}
/*     */ 
/*     */   public void start() throws Exception {
/*  88 */     this.flowID = this.originCallParam.getSessionId();
/*  89 */     prepairGlobalVars(this.originCallParam);
/*  90 */     if (this.flowDef.beforeFlowScript != null) {
/*  91 */       logger.info("execute beforeFlowScript " + this.flowDef.beforeFlowScript);
/*  92 */       doExecScript(this.flowDef.beforeFlowScript);
/*     */     }
/*     */ 
/*  95 */     StepDef firstStep = null;
/*  96 */     if ((this.flowDef.initTransitionDefs != null) && (!this.flowDef.initTransitionDefs.isEmpty())) {
/*  97 */       String theStep = choiseStepFromTransition(this.flowDef.initTransitionDefs);
/*  98 */       if (theStep == null) {
/*  99 */         throw new RuntimeException("BON FLOW ERR: Can't find first step, No initial transition matched ");
/*     */       }
/* 101 */       firstStep = (StepDef)this.flowDef.stepDefs.get(theStep);
/*     */     }
/*     */     else {
/* 104 */       firstStep = (StepDef)this.flowDef.stepDefs.values().iterator().next();
/*     */     }
/* 106 */     exceuteStep(firstStep);
/*     */   }
/*     */ 
	private Object doExecScript(String beforeFlowScript) throws EvalError {
		if (this.bsh == null) {
			this.bsh = new Interpreter();
			bsh.set("bonflowContext", this.flowExprParser);
		}
		return bsh.eval(beforeFlowScript);

	}

	private String choiseStepFromTransition(List<TransitionDef> transitionDefs) throws Exception {
		String nextStep = null;
		for (TransitionDef transDef : transitionDefs) {
			if (this.flowExprParser.evalCond(transDef.expression)) {
				nextStep = transDef.nextStep;
				break;
			}
		}
		return nextStep;
	}

	private void exceuteStep(StepDef curStep) throws Exception {
		logger.info("execute step " + curStep.name + " of flow " + flowID + " sendRequests " + curStep.sendRequests.size());
		FlowStepStatus curflowStatus = new FlowStepStatus();
		curflowStatus.curStep = curStep;
		this.curStepStaus = curflowStatus;
		if (curStep.beforeSendScript != null) {
			logger.debug("execute before step script :" + curStep.beforeSendScript);
			doExecScript(curStep.beforeSendScript);
		}
		for (SendRequestDef sendReq : curStep.sendRequests) {
			CallParam newCallParam = sendReqMsg(originCallParam, sendReq);
			if (newCallParam.getRetCode() != 0) {
				int ret = newCallParam.getRetCode();
				logger.warn("Send Req Msg failed,result=" + newCallParam.getRetCode() + ",session=" + newCallParam.getSessionId());
				// 发送失败
				Message answer = new Message();
				AVP_Unsigned32 errorCodeAVP = new AVP_Unsigned32(Constants.DIAMETER_AVP_SERVICE_RESULT_CODE, Constants.DIAMETER_VENDOR_CT, ret);
				errorCodeAVP.setMandatory(true);
				AVP avpServiceInfomaiton = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, new AVP[] { errorCodeAVP });
				answer.add(new AVP_Unsigned32(ProtocolConstants.DI_RESULT_CODE, ret));
				answer.add(avpServiceInfomaiton);
/* 149 */         addDCCMsgToCtx(sendReq.respVarName, answer);
/*     */       } else {
/* 151 */         curflowStatus.sendedRequest.put(newCallParam.getSessionId(), sendReq.respVarName);
/*     */       }
/*     */     }
/* 154 */     doStepResponse();
/*     */   }
/*     */ 
/*     */   private CallParam sendReqMsg(CallParam callParam, SendRequestDef sendReq) throws Exception {
/* 158 */     Properties avpProp = new Properties();
/* 159 */     String mesDefVal = sendReq.reqMsgDef.asXML();
/*     */ 
/* 161 */     mesDefVal = this.flowExprParser.replaceVars(mesDefVal);
/* 162 */     Element ccrMsgDefEL = Comutils.parseText(mesDefVal).getRootElement();
/* 163 */     if (logger.isDebugEnabled()) {
/* 164 */       logger.debug("dcc req mes format:" + ccrMsgDefEL.asXML());
/*     */     }
/* 166 */     MessageDef msgDef = DccMessageBuilder.makeMessageDef(ccrMsgDefEL);
/* 167 */     msgDef.setType("CCR");
/* 168 */     String svrCtx = null;
/* 169 */     String ccrAreaCode = ccrMsgDefEL.attributeValue("areacode");
/* 170 */     if ((ccrAreaCode == null) || (ccrAreaCode.length() == 0))
/* 171 */       svrCtx = msgDef.getScid() + "@" + DccAvpHelper.getRealmPart(callParam.getServiceContextId());
/*     */     else {
/* 173 */       svrCtx = msgDef.getScid() + "@" + ccrAreaCode + "." + DccAvpHelper.getRealmWithoutAreaCode(callParam.getServiceContextId());
/*     */     }
/*     */ 
/* 177 */     Message ccr = createCCR(callParam.getUserName(), svrCtx);
/* 178 */     ccr = DccMessageBuilder.buildMessage(ccr, msgDef, avpProp);
/* 179 */     String sessionId2 = new AVP_UTF8String(ccr.find(263)).queryValue();
/* 180 */     CallParam newCallParam = new CallParam(sessionId2, svrCtx, ccr, null, null);
/* 181 */     newCallParam.setBussinessCallId(callParam.getBussinessCallId());
/* 182 */     newCallParam.setProcessor(this);
/*     */ 
/* 187 */     RouteInfo r = ChannelServer.findRoute(newCallParam.getServiceContextId());
/* 188 */     int ret = 0;
		String errMsg = null;
		if (r == null) {
			errMsg = "No Route for " + newCallParam.getServiceContextId();
			ret = 3002;// 没有查到路由
		} else if (r.result != 0) {
			errMsg = "Route unavailable for " + newCallParam.getServiceContextId();
			ret = r.result;
		}
		if (ret != 0) {
			newCallParam.setRetCode(3002);
			newCallParam.setResultMsg(errMsg);
			//2012/10/10 没有路由时，把CCR增加到变量中
       		addDCCMsgToCtx(sendReq.reqVarName, ccr);
			return newCallParam;
		}
		newCallParam.setToNode(r.curNode);
		InprogressMessageQueue.getInstance().addRequest(newCallParam);
		r.curNode.getChannel().sendRequest(newCallParam);
		addDCCMsgToCtx(sendReq.reqVarName, ccr);
		return newCallParam;
	}
/*     */ 
/*     */   private Message createCCR(String originHost, String ctxID) {
/* 209 */     Message msg = new Message();
/* 210 */     String session = DiameterUtils.makeSessionID(originHost);
/* 211 */     msg.add(new AVP_OctetString(264, originHost));
/* 212 */     msg.add(new AVP_OctetString(296, DccAvpHelper.getRealmPart(originHost)));
/* 213 */     DccAvpHelper.creatComMessageBeforCCR(msg, session, ctxID);
/* 214 */     return msg;
/*     */   }
/*     */ 
/*     */   private void prepairGlobalVars(CallParam callParam) throws Exception {
/* 218 */     this.flowExprParser.addFlowVarObj("input", new FlowInputVarObj(callParam));
/* 219 */     Element reqData = null;
/* 220 */     if ((callParam.getRequest() instanceof XmlMessage)) {
/* 221 */       reqData = ((XmlMessage)callParam.getRequest()).getDataElement();
/*     */     }
/*     */ 
/* 224 */     this.flowExprParser.addFlowVarObj("inputdata", new FlowInputDataVarObj(reqData));
/*     */ 
/* 227 */     evalFlowVars(this.flowDef.globalVarsDefMap);
/*     */   }
/*     */ 
/*     */   public int process(CallParam callParam)
/*     */   {
/* 233 */     this.originCallParam = callParam;
/*     */     try {
/* 235 */       start();
/*     */     } catch (Exception e) {
/* 237 */       this.originCallParam.setRetCode(11300);
/* 238 */       this.originCallParam.setResultMsg(e.getMessage() + ", please check the flow xml");
/* 239 */       this.originCallParam.getAsynHandler().onCallResult(callParam);
/*     */     }
/* 241 */     return 0;
/*     */   }
/*     */ 
/*     */   public int endProcess(CallParam callParam)
/*     */   {
/* 246 */     if (isFinished()) {
/* 247 */       return -1;
/*     */     }
		String respVarName = this.curStepStaus.sendedRequest.remove(callParam.getSessionId());// sessionID
		if (respVarName == null) {
			logger.warn("respVarName == null," + callParam.getSessionId());
			return -1;
		}
		addDCCMsgToCtx(respVarName, (Message) callParam.getRecvResponse());
/* 255 */     doStepResponse();
/* 256 */     return 0;
/*     */   }
/*     */ 
	private void doStepResponse() {

		if (curStepStaus.canDoStepResponse()) {// 进入当前Step的 Response处理环节
			try {
				doStepResponseProcess();
			} catch (Exception e) {
				doFinishFlowError(e);
			}
		}
		if (this.isFinished()) {
			// 通知回调接口，流程完成
			this.originCallParam.getAsynHandler().onCallResult(originCallParam);
		}
	}

	private void doFinishFlowError(Exception e) {
		logger.warn("flow caught exception and finished ,cur step " + this.curStepStaus.curStep.name + " of flow " + flowID + " ", e);
		finished = true;
		this.originCallParam.setRetCode(Constants.ResultCode.UNKNOW_ERR);
		this.originCallParam.setResultMsg("Flow caught exception and finished :Please contact SGW Admin");
	}

	/**
	 * 流程是否结束
	 * 
	 * @return
	 */
	public boolean isFinished() {
		return finished;
	}

	/**
	 * 对流程定义的变量进行EVAL赋值
	 * 
	 * @param varDefineMap
	 * @throws InvalidExpressionException
	 */
	private void evalFlowVars(Map<String, String> varDefineMap) throws InvalidExpressionException {
		for (Map.Entry<String, String> varEntry : varDefineMap.entrySet()) {
			String expression = varEntry.getValue();
			String value = this.flowExprParser.evalExpression(expression);
			if (logger.isDebugEnabled()) {
         		String step = " step:" + this.curStepStaus.curStep.name;
				logger.debug("evaled expression " + varEntry.getKey() + ":" + " expr:" + varEntry.getValue() + " eval:" + value + step + " of flow " + flowID);
			}
			flowExprParser.addVar(varEntry.getKey(), value);
		}

	}

	// lichangzhen 直接获得Xml2AVPConvetor
	private void addDCCMsgToCtx(String dccMsgID, Message dccMsg) {
		if (dccMsgID == null || dccMsgID.trim().isEmpty()) {
			return;
		}
		dccMsgID = dccMsgID.trim();
		Map<String, ConvMapInfo> allAvpNamesMap = Xml2AVPConvetor.getInstance().getALLNamesMap();
		Map<Integer, ConvMapInfo> allCodesMap = Xml2AVPConvetor.getInstance().getAllCodesMap();
		DCCMsgVarObj varObj = new DCCMsgVarObj(dccMsg, allAvpNamesMap, allCodesMap);
		this.flowExprParser.addFlowVarObj(dccMsgID, varObj);
	}

	/**
	 * 处理当前Step的Response处理环节，包括Step中定义的变量值的解析 transitions的变迁，以及返回值的处理等
	 */
	private void doStepResponseProcess() throws Exception {
		FlowStepStatus flowStatus = this.curStepStaus;
		logger.debug("do step response  process step " + flowStatus.curStep.name + " of flow " + flowID);

		String beforeRespScript = flowStatus.curStep.beforeRespScript;
		if (beforeRespScript != null) {
			logger.debug("execute  step before response script :" + beforeRespScript);
			doExecScript(beforeRespScript);
		}
		// 处理本Step定义的变量
		evalFlowVars(flowStatus.curStep.stepVarsDefMap);
		// 处理跳转或返回
		if (!flowStatus.curStep.transitionDefs.isEmpty()) {
			String nextStep = choiseStepFromTransition(flowStatus.curStep.transitionDefs);
			if (nextStep == null) {// 如果定义了Return定义，则直接Return
				if (flowStatus.curStep.returnDef != null) {
					doFinishFlowNormalReturn();
				} else {
					doFinishFlowNoMatchedTransition();
				}
			} else {
				logger.info("transition from step " + flowStatus.curStep.name + " to " + nextStep + " of flow " + flowID);
				this.exceuteStep(this.flowDef.stepDefs.get(nextStep));
			}
		} else {
			doFinishFlowNormalReturn();
		}
	}

	/**
	 * 没有找到下一步的异常结束
	 */
	private void doFinishFlowNoMatchedTransition() {
		logger.warn("flow  abnormal finished ,no matched transition found,cur step " + this.curStepStaus.curStep.name + " of flow " + flowID);
		finished = true;

		this.originCallParam.setRetCode(Constants.ResultCode.UNKNOW_ERR);
		this.originCallParam.setResultMsg("Flow ERR: No mathced transition found :Please contact SGW Admin");
	}

	/**
	 * 正常结束
	 */
	private void doFinishFlowNormalReturn() {
		if (logger.isInfoEnabled()) {
			logger.info("flow  success finished ,cur step " + this.curStepStaus.curStep.name + " of flow " + flowID);
		}
		finished = true;
		ReturnDef returnDef = this.curStepStaus.curStep.returnDef;
		try {
			int retCode = Constants.ResultCode.SUCCESS;
/* 379 */       if (returnDef.rcCode != null) {
/* 380 */         if (returnDef.rcCode.startsWith("$")) {
/* 381 */           String rcCode = this.flowExprParser.evalExpression(returnDef.rcCode);
/* 382 */           retCode = Integer.valueOf(rcCode).intValue();
/*     */         } else {
/* 384 */           retCode = Integer.valueOf(returnDef.rcCode).intValue();
/*     */         }
/*     */       }
/* 387 */       String returnData = returnDef.returnDATA;
/*     */ 
/* 389 */       String result = this.flowExprParser.replaceVars(returnData);
/* 390 */       this.originCallParam.setRetCode(retCode);
/* 391 */       this.originCallParam.setResultMsg(retCode == 0 ? "SUCCESS" : "FAILED");
/* 392 */       if ((result != null) && (!result.isEmpty()) && (!"null".equals(result))) {
/* 393 */         Document doc = Comutils.parseText(result);
/* 394 */         Element e = doc.getRootElement();
/* 395 */         XmlMessage xmlMessage = new XmlMessage(false);
/* 396 */         xmlMessage.setMID(this.originCallParam.getSessionId());
/* 397 */         xmlMessage.setDS(this.originCallParam.getResultMsg());
/* 398 */         xmlMessage.setRTT(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(Long.valueOf(System.currentTimeMillis())));
/* 399 */         xmlMessage.setRC(String.valueOf(this.originCallParam.getRetCode()));
/* 400 */         xmlMessage.setDataElement(e);
/* 401 */         this.originCallParam.setResponse(xmlMessage);
/*     */       }
/*     */     }
/*     */     catch (Exception e) {
/* 405 */       logger.warn("caught err:" + e);
/* 406 */       this.originCallParam.setRetCode(11206);
/* 407 */       this.originCallParam.setResultMsg("Flow Result ERR: Please contact SGW Admin");
/*     */     }
/*     */   }
/*     */ 
/*     */   public void setFlowExprParser(FlowExpressionParser flowExprParser)
/*     */   {
/* 413 */     this.flowExprParser = flowExprParser;
/*     */   }
/*     */ }

/* Location:           C:\Users\think\Desktop\sgw_2.1.jar
 * Qualified Name:     com.hp.bon.sgw.wkflow.SGWFlowInstance
 * JD-Core Version:    0.6.1
 */